package ntd.protocol.bo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;
import lombok.Data;
import ntd.tool.ToolCrc16;
import ntd.tool.abnormal.ComAbnormal;

import java.util.*;

@Data
public class Ntd212BO {

    // 精确到毫秒的时间戳:QN=YYYYMMDDhhmmsszzz，用来唯一标识一次命令交互
    private String QN;
    // 系统编码ST
    // 32 表示系统类型为地表水体环境污染源
    // 91 实时数据
    private String ST;
    // 命令编号CN
    private String CN;
    // 访问密码PW
    private String PW;
    // 设备唯一标识MN
    private String MN;
    // 拆分包及应答标志Flag - 总包号PNUM - 包号PNO
    private String Flag;
    // 指令参数CP - CP=&&数据区&&
    private String CP;
    private Map<String, String> CPData = new HashMap<>();
    // 包号
    private String PNO;
    // 内容
    private String PNUM;

    public static Ntd212BO parse(String msg) {
        Ntd212BO ntd212BO = new Ntd212BO();
        if (StrUtil.isBlank(msg)) {
            throw new ComAbnormal("212解析异常，数据串为空！");
        }
        if (StrUtil.startWith(msg, "##")) {
            msg = StrUtil.sub(msg, 6, msg.length());
        }
        String msgTemp = StrUtil.subBefore(msg, "&&", false);
        try {
            for (String item : StrUtil.split(msgTemp, ";")) {
                String[] itemArr = StrUtil.splitToArray(item, "=");

                if (BeanUtil.hasNullField(ntd212BO, itemArr[0]) && itemArr.length > 1) {
                    BeanUtil.setFieldValue(ntd212BO, itemArr[0], itemArr[1]);
                }
            }
            // 数据包解析
            String[] datas = StrUtil.subBetweenAll(msg, "&&");
            if (ArrayUtil.isNotEmpty(datas)) {
                String data = datas[0];
                ntd212BO.setCP(StrUtil.wrap(data, "&&"));
                Map<String, String> cpData = ntd212BO.getCPData();
                Opt.ofBlankAble(data).ifPresent(dataNo -> {
                    for (String item : StrUtil.split(dataNo, ";", true, true)) {
                        for (String itemSub : StrUtil.split(item, ",", true, true)) {
                            String[] itemArr = StrUtil.splitToArray(itemSub, "=");
                            cpData.put(itemArr[0], itemArr[1]);
                        }
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ComAbnormal("212解析异常，数据串不符合规范！");
        }
        return ntd212BO;
    }

    public String to212Str() {
        String str212 = "##";
        if (StrUtil.isBlank(getCP())) {
            setCP(cpToStr(getCPData()));
        }
        String data = StrUtil.format("QN={};ST={};CN={};PW={};MN={};", getQN(), getST(), getCN(), getPW(), getMN());
        if (StrUtil.isNotBlank(getPNO())) {
            data += StrUtil.format("PNO={};", getPNO());
        }
        if (StrUtil.isNotBlank(getPNUM())) {
            data += StrUtil.format("PNUM={};", getPNUM());
        }
        if (StrUtil.isNotBlank(getFlag())) {
            data += StrUtil.format("Flag={};", getFlag());
        }
        if (StrUtil.isNotBlank(getCP())) {
            data += StrUtil.format("CP={}", getCP());
        }
        String length = StrUtil.padPre(data.length() + "", 4, '0');
        str212 += length;
        str212 += data;
        str212 += ToolCrc16.crc16(data);
        str212 += "\r\n";
        return str212;
    }

    public static String cpToStr(Map<String, String> CPData) {
        if (MapUtil.isEmpty(CPData)) {
            return "&&&&";
        }

        StrBuilder strBuilder = StrBuilder.create();
        Set<String> keys = CPData.keySet();

        Map<String, List<String>> stringListMap = CollStreamUtil.groupByKey(keys, s -> {
            String[] split = s.split("-");
            return split[0];
        });

        for (Map.Entry<String, List<String>> stringListEntry : stringListMap.entrySet()) {
            for (String str : stringListEntry.getValue()) {
                strBuilder.append(str + "=" + CPData.get(str));
                strBuilder.append(",");
            }
            strBuilder.delTo(strBuilder.length() - 1);
            strBuilder.append(";");
        }
        strBuilder.delTo(strBuilder.length() - 1);

        return StrUtil.format("&&{}&&", strBuilder.toString());
    }

    public static void main(String[] args) throws Exception {
//        StaticLog.info(StrBuilder.create("123456789").delTo(4).toString());

        String str = "##0172QN=20230607115033375;ST=31;CN=2061;PW=123456;MN=TEST-2023060602;Flag=5;CP=&&w01018-Avg=33;w01001-Avg=28;DataTime=20230530020000;f10001-Avg=43;f10011-Avg=31;f11001-Avg=52;&&B981";

        Ntd212BO ntd212BO = Ntd212BO.parse(str);

        ntd212BO.setCP(null);

        StaticLog.info(ntd212BO.to212Str());

        Ntd212BO.parse(ntd212BO.to212Str());

        Map<String, String> map = new HashMap<>();

//        map.put("DataTime", "20230607100000");
//        // 查询因子列表
////            map.put(fmFactorDO.getFactorCode() + "-Rtd", String.valueOf(RandomUtil.randomInt(1, 100)));
//        map.put("010-Avg", String.valueOf(RandomUtil.randomInt(1, 100)));
//        map.put("011-Avg", String.valueOf(RandomUtil.randomInt(1, 100)));
//        map.put("012-Avg", String.valueOf(RandomUtil.randomInt(1, 100)));
//        map.put("013-Avg", String.valueOf(RandomUtil.randomInt(1, 100)));
//
//        StaticLog.info(cpToStr(map));
    }

}
